package com.gitee.deament.server.core.cli.db.hash;

import cn.hutool.core.util.NumberUtil;
import com.gitee.deament.server.config.SystemConfig;
import com.gitee.deament.server.core.annotation.CliHander;
import com.gitee.deament.server.core.cli.AbstractCli;
import com.gitee.deament.server.core.data.ConnectData;
import com.gitee.deament.server.core.data.datatype.Value;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * HINCRBY
 * HINCRBY key field increment
 *
 * 为哈希表 key 中的域 field 的值加上增量 increment 。
 *
 * 增量也可以为负数，相当于对给定域进行减法操作。
 *
 * 如果 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。
 *
 * 如果域 field 不存在，那么在执行命令前，域的值被初始化为 0 。
 *
 * 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。
 *
 * 本操作的值被限制在 64 位(bit)有符号数字表示之内。
 *
 * 可用版本：
 * >= 2.0.0
 *
 * 时间复杂度：
 * O(1)
 *
 * 返回值：
 * 执行 HINCRBY 命令之后，哈希表 key 中域 field 的值。
 * @author deament
 */
@CliHander(command = "HINCRBY")
public class HINCRBYcli extends AbstractCli {
    @Override
    public void executeCli(ChannelHandlerContext channelHandlerContext, String command) {
        List<String> values = getValues(command);
        if (values.size() != 4) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR wrong number of arguments for 'HINCRBY' command"));
            return;
        }
        int db = ConnectData.SELECT_DB_STORAGE.getUseDB(channelHandlerContext.channel().id().asLongText());
        String hash=values.get(1);
        String field=values.get(2);
        String increaseNum=values.get(3);
        if(!NumberUtil.isInteger(increaseNum)){
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR value is not an integer or out of range"));
        }
        Integer increaseNumber=Integer.parseInt(increaseNum);
        Value<Map<String,String>> stringData = SystemConfig.dbData.getHashData(db, hash);
        Value<Map<String,String>> newValue= new Value<>();
        Map<String,String> fieldAndValue= new HashMap<>(1);
        fieldAndValue.put(field, increaseNum);
        newValue.setValue(fieldAndValue);

        if(stringData==null||stringData.getValue().get(field)==null){
            SystemConfig.dbData.setHashData(db, hash, field, increaseNum);
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(increaseNumber+""));
        } else{
            Date date = stringData.getExpirDateTime();
            if ((date.compareTo(new Date())) <= 0) {
                SystemConfig.dbData.setHashData(db, hash, field, increaseNum);
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(increaseNumber+""));
                return;
            }
            if(NumberUtil.isInteger(stringData.getValue().get(field))){
                Integer value=increaseNumber+Integer.parseInt(stringData.getValue().get(field));
                fieldAndValue.put(field,value+"");

                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(value+""));
            }else{
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR value is not an integer or out of range"));
                return;

            }
        }
    }
}
